/**
 *
 */
package jp.seraph.same.model;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.NullArgumentException;

import jp.seraph.jsade.model.JointIdentifierContainer;
import jp.seraph.jsade.model.ObjectContainer;
import jp.seraph.jspf.pose.DefaultPose;
import jp.seraph.jspf.pose.Pose;
import jp.seraph.jspf.pose.PoseManager;

/**
 *
 */
public class DefaultPoseCollectionModel implements PoseCollectionModel {
    public DefaultPoseCollectionModel(PoseManager aManager, ObjectContainer aContainer, JointIdentifierContainer aIdentifierContainer, JointPositionMapper aPositionMapper) {
        mManager = aManager;
        mListeners = new ArrayList<PoseCollectionModelListener>();
        mContainer = aContainer;
        mIdentifierContainer = aIdentifierContainer;
        mPositionMapper = aPositionMapper;
        mSelectedPoseIndex = -1;

        mPoseNames = new ArrayList<String>();
        for (String tPoseName : aManager.getPoseNames()) {
            mPoseNames.add(tPoseName);
        }

        mSelectedPose = new DefaultPoseModel(mContainer, mIdentifierContainer, mPositionMapper, new DefaultPose());
    }

    private List<PoseCollectionModelListener> mListeners;
    private List<String> mPoseNames;
    private PoseManager mManager;
    private ObjectContainer mContainer;
    private JointIdentifierContainer mIdentifierContainer;
    private JointPositionMapper mPositionMapper;
    private PoseModel mSelectedPose;
    private int mSelectedPoseIndex;

    /**
     *
     * @see jp.seraph.same.model.PoseCollectionModel#addListener(jp.seraph.same.model.PoseCollectionModelListener)
     */

    public void addListener(PoseCollectionModelListener aListener) {
        if (aListener == null)
            throw new NullArgumentException("aListener");

        mListeners.add(aListener);
    }

    /**
     *
     * @see jp.seraph.same.model.PoseCollectionModel#getPose(java.lang.String)
     */

    public PoseModel getPose(String poseName) {
        return new DefaultPoseModel(mContainer, mIdentifierContainer, mPositionMapper, new DefaultPose(mManager.getPose(poseName)));
    }

    /**
     *
     * @see jp.seraph.same.model.PoseCollectionModel#getPose(int)
     */

    public PoseModel getPose(int index) {
        return this.getPose(mPoseNames.get(index));
    }

    /**
     *
     * @see jp.seraph.same.model.PoseCollectionModel#getPoseCount()
     */

    public int getPoseCount() {
        return mPoseNames.size();
    }

    /**
     *
     * @see jp.seraph.same.model.PoseCollectionModel#getPoseName(int)
     */

    public String getPoseName(int index) {
        return mPoseNames.get(index);
    }

    /**
     *
     * @see jp.seraph.same.model.PoseCollectionModel#getSelectedPose()
     */

    public PoseModel getSelectedPose() {
        return mSelectedPose;
    }

    /**
     *
     * @see jp.seraph.same.model.PoseCollectionModel#getSelectedPoseName()
     */

    public String getSelectedPoseName() {
        if (mSelectedPoseIndex == -1)
            return "";

        return this.getPoseName(mSelectedPoseIndex);
    }

    /**
     *
     * @see jp.seraph.same.model.PoseCollectionModel#removeListener(jp.seraph.same.model.PoseCollectionModelListener)
     */

    public boolean removeListener(PoseCollectionModelListener listener) {
        return mListeners.remove(listener);
    }

    /**
     *
     * @see jp.seraph.same.model.PoseCollectionModel#selectPose(java.lang.String)
     */

    public void selectPose(String poseName) {
        this.selectPose(mPoseNames.indexOf(poseName));
    }

    /**
     *
     * @see jp.seraph.same.model.PoseCollectionModel#selectPose(int)
     */

    public void selectPose(int index) {
        if (index != mSelectedPoseIndex) {
            mSelectedPose = this.getPose(index);
            mSelectedPoseIndex = index;
            onSelectedPoseChanged(index, mPoseNames.get(index));
        }
    }

    /**
     *
     * @see jp.seraph.same.model.PoseCollectionModel#setPose(java.lang.String,
     *      jp.seraph.same.model.PoseModel)
     */

    public void setPose(String poseName, PoseModel pose) {
        this.setPose(poseName, pose.createPose());
    }

    /**
     *
     * @see jp.seraph.same.model.PoseCollectionModel#removePose(java.lang.String)
     */

    public void removePose(String poseName) {
        if(mPoseNames.get(mSelectedPoseIndex).equals(poseName))
            selectPose(mSelectedPoseIndex-1);

        mManager.removePose(poseName);
        mPoseNames.remove(poseName);
        onPoseCountChanged();
    }

    /**
     *
     * @see jp.seraph.same.model.PoseCollectionModel#setPose(java.lang.String,
     *      jp.seraph.jspf.pose.Pose)
     */

    public void setPose(String poseName, Pose pose) {
        boolean tAdd = !mPoseNames.contains(poseName);
        mManager.setPose(poseName, pose);
        if (tAdd) {
            mPoseNames.add(poseName);
            onPoseCountChanged();
        }
    }

    protected void onSelectedPoseChanged(int aIndex, String aPoseName) {
        for (PoseCollectionModelListener tListener : mListeners) {
            tListener.SelectedPoseChanged(this, aIndex, aPoseName);
        }
    }

    protected void onPoseCountChanged() {
        for (PoseCollectionModelListener tListener : mListeners) {
            tListener.PoseCountChanged(this);
        }
    }
}
